From f7b7cc22e61cc700b9bceb5c6552701f6e3e0cd2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 1 Mar 2012 00:56:51 -0500 Subject: [PATCH] xi2: Translate touch events Translate XI_TouchBegin/Update/End to GDK_TOUCH_BEGIN/UPDATE/END events. At the same time, set pointer-emulated flags on button events with XIPointerEmulated and on touch events emulating the pointer. --- gdk/x11/gdkdevice-xi2.c | 34 ++++- gdk/x11/gdkdevicemanager-x11.c | 4 + gdk/x11/gdkdevicemanager-xi2.c | 250 ++++++++++++++++++++++++--------- gdk/x11/gdkprivate-x11.h | 5 +- 4 files changed, 223 insertions(+), 70 deletions(-) diff --git a/gdk/x11/gdkdevice-xi2.c b/gdk/x11/gdkdevice-xi2.c index 96fd2c5651..4b37a7a82f 100644 --- a/gdk/x11/gdkdevice-xi2.c +++ b/gdk/x11/gdkdevice-xi2.c @@ -386,6 +386,7 @@ gdk_x11_device_xi2_grab (GdkDevice *device, guint32 time_) { GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device); + GdkX11DeviceManagerXI2 *device_manager_xi2; GdkDisplay *display; XIEventMask mask; Window xwindow; @@ -393,6 +394,7 @@ gdk_x11_device_xi2_grab (GdkDevice *device, gint status; display = gdk_device_get_display (device); + device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (gdk_display_get_device_manager (display)); /* FIXME: confine_to is actually unused */ @@ -407,7 +409,9 @@ gdk_x11_device_xi2_grab (GdkDevice *device, } mask.deviceid = device_xi2->device_id; - mask.mask = _gdk_x11_device_xi2_translate_event_mask (event_mask, &mask.mask_len); + mask.mask = _gdk_x11_device_xi2_translate_event_mask (device_manager_xi2, + event_mask, + &mask.mask_len); #ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_NOGRABS) @@ -623,10 +627,17 @@ gdk_x11_device_xi2_select_window_events (GdkDevice *device, GdkEventMask event_mask) { GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device); + GdkX11DeviceManagerXI2 *device_manager_xi2; + GdkDisplay *display; XIEventMask evmask; + display = gdk_device_get_display (device); + device_manager_xi2 = GDK_X11_DEVICE_MANAGER_XI2 (gdk_display_get_device_manager (display)); + evmask.deviceid = device_xi2->device_id; - evmask.mask = _gdk_x11_device_xi2_translate_event_mask (event_mask, &evmask.mask_len); + evmask.mask = _gdk_x11_device_xi2_translate_event_mask (device_manager_xi2, + event_mask, + &evmask.mask_len); XISelectEvents (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window), @@ -636,10 +647,14 @@ gdk_x11_device_xi2_select_window_events (GdkDevice *device, } guchar * -_gdk_x11_device_xi2_translate_event_mask (GdkEventMask event_mask, - gint *len) +_gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager_xi2, + GdkEventMask event_mask, + gint *len) { guchar *mask; + gint minor; + + g_object_get (device_manager_xi2, "minor", &minor, NULL); *len = XIMaskLen (XI_LASTEVENT); mask = g_new0 (guchar, *len); @@ -688,6 +703,17 @@ _gdk_x11_device_xi2_translate_event_mask (GdkEventMask event_mask, XISetMask (mask, XI_FocusOut); } +#ifdef XINPUT_2_2 + /* XInput 2.2 includes multitouch support */ + if (minor >= 2 && + event_mask & GDK_TOUCH_MASK) + { + XISetMask (mask, XI_TouchBegin); + XISetMask (mask, XI_TouchUpdate); + XISetMask (mask, XI_TouchEnd); + } +#endif /* XINPUT_2_2 */ + return mask; } diff --git a/gdk/x11/gdkdevicemanager-x11.c b/gdk/x11/gdkdevicemanager-x11.c index 0fff0ebcd8..75470636a9 100644 --- a/gdk/x11/gdkdevicemanager-x11.c +++ b/gdk/x11/gdkdevicemanager-x11.c @@ -52,7 +52,11 @@ _gdk_x11_device_manager_new (GdkDisplay *display) int major, minor; major = 2; +#ifdef XINPUT_2_2 + minor = 2; +#else minor = 0; +#endif /* XINPUT_2_2 */ if (!_gdk_disable_multidevice && XIQueryVersion (xdisplay, &major, &minor) != BadRequest) diff --git a/gdk/x11/gdkdevicemanager-xi2.c b/gdk/x11/gdkdevicemanager-xi2.c index 7b66d92b8c..ecd1a4f909 100644 --- a/gdk/x11/gdkdevicemanager-xi2.c +++ b/gdk/x11/gdkdevicemanager-xi2.c @@ -27,6 +27,7 @@ #include "gdkprivate-x11.h" #include "gdkintl.h" #include "gdkkeysyms.h" +#include "gdkinternals.h" #ifdef XINPUT_2 @@ -164,8 +165,10 @@ _gdk_x11_device_manager_xi2_select_events (GdkDeviceManager *device_manager, static void translate_valuator_class (GdkDisplay *display, GdkDevice *device, - XIValuatorClassInfo *info, - gint n_valuator) + Atom valuator_label, + gdouble min, + gdouble max, + gdouble resolution) { static gboolean initialized = FALSE; static Atom label_atoms [GDK_AXIS_LAST] = { 0 }; @@ -186,24 +189,19 @@ translate_valuator_class (GdkDisplay *display, for (i = GDK_AXIS_IGNORE; i < GDK_AXIS_LAST; i++) { - if (label_atoms[i] == info->label) + if (label_atoms[i] == valuator_label) { use = i; break; } } - if (info->label != None) - label = gdk_x11_xatom_to_atom_for_display (display, info->label); + if (valuator_label != None) + label = gdk_x11_xatom_to_atom_for_display (display, valuator_label); else label = GDK_NONE; - _gdk_device_add_axis (device, - label, - use, - info->min, - info->max, - info->resolution); + _gdk_device_add_axis (device, label, use, min, max, resolution); } static void @@ -212,7 +210,7 @@ translate_device_classes (GdkDisplay *display, XIAnyClassInfo **classes, guint n_classes) { - gint i, n_valuator = 0; + gint i; g_object_freeze_notify (G_OBJECT (device)); @@ -234,10 +232,14 @@ translate_device_classes (GdkDisplay *display, } break; case XIValuatorClass: - translate_valuator_class (display, device, - (XIValuatorClassInfo *) class_info, - n_valuator); - n_valuator++; + { + XIValuatorClassInfo *valuator_info = (XIValuatorClassInfo *) class_info; + translate_valuator_class (display, device, + valuator_info->label, + valuator_info->min, + valuator_info->max, + valuator_info->resolution); + } break; default: /* Ignore */ @@ -893,6 +895,11 @@ get_event_window (GdkEventTranslator *translator, case XI_ButtonPress: case XI_ButtonRelease: case XI_Motion: +#ifdef XINPUT_2_2 + case XI_TouchUpdate: + case XI_TouchBegin: + case XI_TouchEnd: +#endif /* XINPUT_2_2 */ { XIDeviceEvent *xev = (XIDeviceEvent *) ev; @@ -1117,51 +1124,39 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, XIDeviceEvent *xev = (XIDeviceEvent *) ev; GdkDevice *source_device; - switch (xev->detail) + if (ev->evtype == XI_ButtonPress && + (xev->detail >= 4 && xev->detail <= 7)) + { + /* Button presses of button 4-7 are scroll events */ + event->scroll.type = GDK_SCROLL; + + if (xev->detail == 4) + event->scroll.direction = GDK_SCROLL_UP; + else if (xev->detail == 5) + event->scroll.direction = GDK_SCROLL_DOWN; + else if (xev->detail == 6) + event->scroll.direction = GDK_SCROLL_LEFT; + else + event->scroll.direction = GDK_SCROLL_RIGHT; + + event->scroll.window = window; + event->scroll.time = xev->time; + event->scroll.x = (gdouble) xev->event_x; + event->scroll.y = (gdouble) xev->event_y; + event->scroll.x_root = (gdouble) xev->root_x; + event->scroll.y_root = (gdouble) xev->root_y; + + event->scroll.device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->deviceid)); + + source_device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->sourceid)); + gdk_event_set_source_device (event, source_device); + + event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + } + else { - case 4: - case 5: - case 6: - case 7: - /* Button presses of button 4-7 are scroll events */ - if (ev->evtype == XI_ButtonPress) - { - event->scroll.type = GDK_SCROLL; - - if (xev->detail == 4) - event->scroll.direction = GDK_SCROLL_UP; - else if (xev->detail == 5) - event->scroll.direction = GDK_SCROLL_DOWN; - else if (xev->detail == 6) - event->scroll.direction = GDK_SCROLL_LEFT; - else - event->scroll.direction = GDK_SCROLL_RIGHT; - - event->scroll.window = window; - event->scroll.time = xev->time; - event->scroll.x = (gdouble) xev->event_x; - event->scroll.y = (gdouble) xev->event_y; - event->scroll.x_root = (gdouble) xev->root_x; - event->scroll.y_root = (gdouble) xev->root_y; - - event->scroll.device = g_hash_table_lookup (device_manager->id_table, - GUINT_TO_POINTER (xev->deviceid)); - - source_device = g_hash_table_lookup (device_manager->id_table, - GUINT_TO_POINTER (xev->sourceid)); - gdk_event_set_source_device (event, source_device); - - event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); - break; - } - /* Button presses of button 4-7 are scroll events, so ignore the release */ - else if (ev->evtype == XI_ButtonRelease) - { - return_val = FALSE; - break; - } - /* else (XI_ButtonRelease) fall thru */ - default: event->button.type = (ev->evtype == XI_ButtonPress) ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE; event->button.window = window; @@ -1194,9 +1189,13 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, } event->button.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + event->button.button = xev->detail; } + if (xev->flags & (XIPointerEmulated | XITouchEmulatingPointer)) + _gdk_event_set_pointer_emulated (event, TRUE); + if (return_val == FALSE) break; @@ -1211,15 +1210,14 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, break; } + case XI_Motion: { XIDeviceEvent *xev = (XIDeviceEvent *) ev; GdkDevice *source_device; event->motion.type = GDK_MOTION_NOTIFY; - event->motion.window = window; - event->motion.time = xev->time; event->motion.x = (gdouble) xev->event_x; event->motion.y = (gdouble) xev->event_y; @@ -1235,6 +1233,9 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + if (xev->flags & (XIPointerEmulated | XITouchEmulatingPointer)) + _gdk_event_set_pointer_emulated (event, TRUE); + /* There doesn't seem to be motion hints in XI */ event->motion.is_hint = FALSE; @@ -1254,6 +1255,124 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator, } } break; + +#ifdef XINPUT_2_2 + case XI_TouchBegin: + case XI_TouchEnd: + { + XIDeviceEvent *xev = (XIDeviceEvent *) ev; + GdkDevice *source_device; + + if (ev->evtype == XI_TouchBegin) + event->touch.type = GDK_TOUCH_BEGIN; + else if (ev->evtype == XI_TouchEnd) + event->touch.type = GDK_TOUCH_END; + + event->touch.window = window; + event->touch.time = xev->time; + event->touch.x = (gdouble) xev->event_x; + event->touch.y = (gdouble) xev->event_y; + event->touch.x_root = (gdouble) xev->root_x; + event->touch.y_root = (gdouble) xev->root_y; + + event->touch.device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->deviceid)); + + source_device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->sourceid)); + gdk_event_set_source_device (event, source_device); + + event->touch.axes = translate_axes (event->touch.device, + event->touch.x, + event->touch.y, + event->touch.window, + &xev->valuators); + + if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW) + { + GdkDevice *device = event->touch.device; + + /* Update event coordinates from axes */ + gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x); + gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y); + } + + event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + + if (ev->evtype == XI_TouchBegin) + event->touch.state |= GDK_BUTTON1_MASK; + + event->touch.sequence = GUINT_TO_POINTER (xev->detail); + + if (xev->flags & XITouchEmulatingPointer) + { + event->touch.emulating_pointer = TRUE; + _gdk_event_set_pointer_emulated (event, TRUE); + } + + if (return_val == FALSE) + break; + + if (!set_screen_from_root (display, event, xev->root)) + { + return_val = FALSE; + break; + } + + if (ev->evtype == XI_TouchBegin) + set_user_time (event); + } + break; + + case XI_TouchUpdate: + { + XIDeviceEvent *xev = (XIDeviceEvent *) ev; + GdkDevice *source_device; + + event->touch.window = window; + event->touch.sequence = GUINT_TO_POINTER (xev->detail); + event->touch.type = GDK_TOUCH_UPDATE; + event->touch.time = xev->time; + event->touch.x = (gdouble) xev->event_x; + event->touch.y = (gdouble) xev->event_y; + event->touch.x_root = (gdouble) xev->root_x; + event->touch.y_root = (gdouble) xev->root_y; + + event->touch.device = g_hash_table_lookup (device_manager->id_table, + GINT_TO_POINTER (xev->deviceid)); + + source_device = g_hash_table_lookup (device_manager->id_table, + GUINT_TO_POINTER (xev->sourceid)); + gdk_event_set_source_device (event, source_device); + + event->touch.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group); + + event->touch.state |= GDK_BUTTON1_MASK; + + if (xev->flags & XITouchEmulatingPointer) + { + event->touch.emulating_pointer = TRUE; + _gdk_event_set_pointer_emulated (event, TRUE); + } + + event->touch.axes = translate_axes (event->touch.device, + event->touch.x, + event->touch.y, + event->touch.window, + &xev->valuators); + + if (gdk_device_get_mode (event->touch.device) == GDK_MODE_WINDOW) + { + GdkDevice *device = event->touch.device; + + /* Update event coordinates from axes */ + gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_X, &event->touch.x); + gdk_device_get_axis (device, event->touch.axes, GDK_AXIS_Y, &event->touch.y); + } + } + break; +#endif + case XI_Enter: case XI_Leave: { @@ -1350,7 +1469,8 @@ gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator) GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK | - GDK_FOCUS_CHANGE_MASK); + GDK_FOCUS_CHANGE_MASK | + GDK_TOUCH_MASK); } static void @@ -1364,7 +1484,9 @@ gdk_x11_device_manager_xi2_select_window_events (GdkEventTranslator *translator, device_manager = GDK_DEVICE_MANAGER (translator); event_mask.deviceid = XIAllMasterDevices; - event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (evmask, &event_mask.mask_len); + event_mask.mask = _gdk_x11_device_xi2_translate_event_mask (GDK_X11_DEVICE_MANAGER_XI2 (device_manager), + evmask, + &event_mask.mask_len); _gdk_x11_device_manager_xi2_select_events (device_manager, window, &event_mask); g_free (event_mask.mask); diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 551391e510..98d7732fee 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -245,8 +245,9 @@ void _gdk_x11_device_xi_translate_axes (GdkDevice *device, #endif #ifdef XINPUT_2 -guchar * _gdk_x11_device_xi2_translate_event_mask (GdkEventMask event_mask, - gint *len); +guchar * _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager_xi2, + GdkEventMask event_mask, + gint *len); guint _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state, XIButtonState *buttons_state, XIGroupState *group_state); -- 2.30.2